package edu.scau.mis.system.security.service;

import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import edu.scau.mis.core.utils.RedisCache;
import edu.scau.mis.system.security.domain.LoginUser;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
public class TokenService {

    private int expireMinute = 1440; // 设置过期时间默认1天即1440分钟
    protected static final long MILLIS_SECOND = 1000; //秒
    protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND; //分钟
    private SignatureAlgorithm alg = SignatureAlgorithm.HS512; // 签名算法
    private String secret = "mis_token_secret";

    public static final String TOKEN_PREFIX = "Bearer "; //令牌前缀

    /* 内存存储loginUser用于测试, 后期使用Redis存储登录用户对象loginUser */
//    private LoginUser loginUser;
// 删除原来的private LoginUser loginUser
    @Autowired
    private RedisCache redisCache;
    /**
     * 生成token
     * @param subject 主题
     * @param expireTime 过期时间
     * @return 令牌
     */
    public String createToken(String subject,long expireTime) {
        Date issuedAt = new Date(); // 签发时间
        Date expiration = new Date(expireTime); //过期时间
        String token = Jwts.builder()
                .setHeaderParam("typ", "JWT") // 设置header参数
                .setSubject(subject)//设置payload_jwt的主题
                .setIssuedAt(issuedAt) // 设置payload_jwt的签发时间
                .setExpiration(expiration) // 设设置payload_jwt的过期时间
                .signWith(alg, secret) // 设置signature
                .compact();
        return token;
    }


    /**
     * 解析token
     * @param token
     * @return
     */
    public Claims parseToken(String token) {
        // 判断token是否有前缀Bearer，有则删除
        if (StrUtil.isNotEmpty(token) && token.startsWith(TOKEN_PREFIX)){
            token = token.replace(TOKEN_PREFIX, "");
        }
        try {
            return Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token)
                    .getBody();
        } catch (Exception e) {
            return null;
        }
    }
    /**
     * 生成token并redis存储loginUser
     * @param loginUser
     * @return 令牌
     */
    public String generateToken(LoginUser loginUser){
        String subject = loginUser.getUsername()+ IdUtil.getSnowflakeNextIdStr();
        long expireTime = new Date().getTime() + MILLIS_MINUTE * expireMinute;
        // 1. 生成token
        String token = createToken(subject, expireTime);
        // 3. 设置loginUser过期时间，根据redisKey将loginUser存入Redis
        loginUser.setExpireTime(expireTime); //设定登录用户过期时间
        redisCache.setCacheObject(subject,loginUser,expireMinute, TimeUnit.MINUTES);
        return token;
    }

    /**
     * 解析request中token获取loginUser
     * @param request http请求
     * @return loginUser
     */
    public LoginUser getLoginUser(HttpServletRequest request) {
        // 1. 从请求头中获取token
        String token = request.getHeader("Authorization");
        LoginUser loginUser = null;
        if(StrUtil.isNotEmpty(token)) {
            // 2. 解析token获得claims
            Claims claims = parseToken(token);
            if (claims == null) {
                return null;
            }
            // 3. 得到用户信息，生成redisKey
            String subject = claims.getSubject();
            // 4. 根据redisKey从Redis中查询loginUser
            loginUser = redisCache.getCacheObject(subject);
        }
        return loginUser;
    }

}
